package com.example.ormsqlsplicingframe1.warpper;

import com.baomidou.mybatisplus.annotation.TableField;
import com.example.ormsqlsplicingframe1.note.*;
import com.example.ormsqlsplicingframe1.orm.Util.StringUtil;
import com.example.ormsqlsplicingframe1.orm.note.Title;
import com.example.ormsqlsplicingframe1.session.SessionUtil;
import com.example.ormsqlsplicingframe1.sql.ConditionSql;
import com.example.ormsqlsplicingframe1.sql.impl.UpdateImpl;
import com.example.ormsqlsplicingframe1.utlis.CopyUtils;
import com.example.ormsqlsplicingframe1.utlis.GetDate;
import com.example.ormsqlsplicingframe1.utlis.GetGenerics;
import com.example.ormsqlsplicingframe1.utlis.ObjValue;
import lombok.SneakyThrows;
import org.springframework.beans.BeanUtils;

import java.lang.reflect.Field;
import java.util.List;
import java.util.function.Consumer;

public class UpdateSqlWrapper<E> {


    //TODO 如果没有set情况下不执行

    private UpdateImpl update = new UpdateImpl();

    private E object;

    //第二个对象
    private E obj;

    //记录标题 只要第一次
    private int titleAdd =0;

    //记录主键字段所在位置
    private Field fieldId;

    //是否找到主键
    private boolean isFieldId =false;

    //是否使用了set方法
    private boolean isExecute = false;



    @SneakyThrows
    public UpdateSqlWrapper(E object) {
        this.object = object;

        Object o = object.getClass().newInstance();
        this.obj =  (E) o ;

        CopyUtils.UpdateCopy(object,obj);
    }



    public UpdateSqlWrapper<E> updateField(Consumer<E> consumer) {
        consumer.accept(obj);
        return this;
    }

    public String sql(){


        return update.getSql();
    }

    @SneakyThrows
    public int execute(){

        wrapper();
        if (isExecute){
            return SessionUtil.getSession().update(update);
        }
      return 0;
    }

    private void wrapper(){
        Class<?> aClass = null;
        if (!SessionUtil.getSession().isOpenTransaction()){
            aClass = object.getClass();
            this.obj = object;
        }else {
            aClass = object.getClass();
        }
        wrapper(aClass);
    }



    @SneakyThrows
    private void wrapper(Class<?> aClass){

        Title title = aClass.getAnnotation(Title.class);

        if (title != null && titleAdd ==0){
            titleAdd =1;
            update.table(title.titleName());
        }


        Field[] fields = aClass.getDeclaredFields();
        for (Field field : fields) {
            field.setAccessible(true);
            JoinFieldMajorKey key = field.getAnnotation(JoinFieldMajorKey.class);
            if (key != null){
                fieldId = field;
                isFieldId =true;
            }
           if (field.getAnnotation(TableField.class) != null && field.getAnnotation(TableField.class).exist()){
               update.fields(fi ->{
                       try {
                           Object value = field.get(object);
                           if (value != null){
                               isExecute = true;
                           }
                           JoinDate date = field.getAnnotation(JoinDate.class);
                           if (date != null && date.value() == JoinDateEnum.UPDATE_TIME){

                               value = GetDate.date();
                               field.set(object,GetDate.date(value));
                           }

                           if (field.getType() == List.class){
                               value = GetGenerics.listChangeSingle(value);
                           }
                           fi.field(StringUtil.javaTurnSql(field.getName()),value);
                       } catch (Exception e) {
                           e.printStackTrace();
                       }
                   });
           }
        }

      if (isFieldId){
          fieldId.setAccessible(true);
          update.where(wh ->{
              try {
                  JoinWhere where = fieldId.getAnnotation(JoinWhere.class);
                  if (where != null){
                      if (where.condition() == ConditionEnum.eq) wh.eq(StringUtil.javaTurnSql(fieldId.getName()),fieldId.get(obj));
                  }else {
                      wh.eq(StringUtil.javaTurnSql(fieldId.getName()),fieldId.get(obj));
                  }
              } catch (IllegalAccessException e) {
                  e.printStackTrace();
              }
          });
      }else {
          wrapper(aClass.getSuperclass());
      }

    }


    public UpdateSqlWrapper() {
    }




    public  static <E> UpdateSqlWrapper<E> newInstance(E object) {
        return new UpdateSqlWrapper(object);
    }

}
